/*
 * Graph.cpp
 *
 *  Created on: 15/09/2009
 *      Author: mario
 */

#include "Graph.h"

Graph::Graph() {
	vertexList = new List();
	setVertexQty(0);
	weightMode = DISTANCE_WEIGHT_MODE; //DEFAULT
}

Graph::~Graph() {
	//std::cout << "Kill graph\n";
	delete vertexList;
}

int Graph::createEdge(string id, string idFrom, string idTo, float length, float maxVel)
{
	if (!validateEdge(idFrom, idTo)){
		return VERTEX_NOT_FOUND;
	}

	Vertex* vertex = getVertex(idFrom);
	if (vertex != null) {
		return (vertex->createEdge(id, idFrom, idTo, length, maxVel));
	}
	return VERTEX_NOT_FOUND;
}

bool Graph::validateEdge(string idFrom, string idTo){
	Vertex* from = getVertex(idFrom);
	Vertex* to = getVertex(idTo);

	return (from != null) && (to != null);
}

Edge* Graph::getEdge(string id) const{
	for (int i = 0; i < getVertexQty(); i++) {
		VertexNode* node = (VertexNode*) getVertexList()->get(i);
		Vertex* v =  node->getNodeValue();
		Edge* e = v->getEdge(id);
		if (e != NULL){
			return e;
		}
	}
	return NULL;
}

int Graph::createVertex(string id, float x, float y)
{
	//Cheks for duplicate ID's
	if (getVertex(id) != NULL) return ID_REPEATED;
	else {
		//Cheks for vertex in the same position
		if (getPosition(x,y) != NULL) return POSITION_REPEATED;
		else {
			Vertex* vertex = new Vertex(id, x, y);
			VertexNode* node = new VertexNode();
			if ((vertex  == NULL) || (node == NULL)) return MEMORY_ERROR; 
			node->setNodeValue(vertex);
			getVertexList()->add(node);
			setVertexQty(getVertexQty() + 1);
			return 0;
		}
	}
}

Vertex* Graph::getVertex(string id) const
{
	for (int i = 0; i < getVertexQty(); i++) {
		VertexNode* node = (VertexNode*) getVertexList()->get(i);
		Vertex* v =  node->getNodeValue();
		string value = v->getId();
		if (value.compare(id) == 0) {
			return node->getNodeValue();
		}
	}
	return null;
}

Vertex* Graph::getPosition(float posX, float posY)
{
	for (int i = 0; i < getVertexQty(); i++) {
		VertexNode* node = (VertexNode*) getVertexList()->get(i);
		Vertex* v =  node->getNodeValue();
		float x = v->getX();
		float y = v->getY();
		if ((x == posX) && (y == posY)) {
			return node->getNodeValue();
		}
	}
	return null;
}

int Graph::getVertexQty() const
{
    return vertexQty;
}

void Graph::setVertexQty(int vertexQty)
{
    this->vertexQty = vertexQty;
}

List* Graph::getVertexList() const
{
    return vertexList;
}

void Graph::setVertexList(List* vertexList)
{
    this->vertexList = vertexList;
}

int Graph::getIndexOfVertex(Vertex* vertex) {
	for (int i = 0; i < getVertexList()->getSize(); i++) {
		if (vertex->getId().compare(((VertexNode*)getVertexList()->get(i))->getNodeValue()->getId()) == 0) {
			return i;
		}
	}
	return -1;
}

float Graph::getEdgeWeight(Edge* edge) {
	if (edge != NULL) {
		if (weightMode == DISTANCE_WEIGHT_MODE) {
			return edge->getLength();
		}
		if (weightMode == TIME_WEIGHT_MODE) {
			return edge->getTime();
		}
		return edge->getLength();
	}
	return 0.0;
}

void Graph::setDistanceWeightMode() {
	weightMode = DISTANCE_WEIGHT_MODE;
}

void Graph::setTimeWeightMode() {
	weightMode = TIME_WEIGHT_MODE;
}